<?php

class CStringSlice extends CString {
	var $RealString;
	var $From;
	var $Len;
	
	function Init($str, $from, $len) {
		$this->RealString = $str;
		$this->From = $from;
		$this->Len = min($len, $str->Length() - $from);
	}
	
	function Length() {
		return $this->Len;
	}
	
	function &Characters($from, $len) {
		$from = $this->From + $from;
		$len = min($len, $this->Len);
		
		$x = &$this->RealString->Characters($from, $len);
		return $x;
	}
	
	function Substring($from, $len) {
		$from = $this->From + $from;
		$len = min($len, $this->Len);
		
		return new CStringSlice($this->RealString, $from, $len);
	}
}

class CStringChain extends CString {
	var $RealStrings;
	
	function Init($strings) {
		$this->RealStrings = $strings;
	}
	
	var $Length;
	function _CalculateLength() {
		if (!is_null($this->Length))
			return;
			
		$this->Length = 0;
		foreach ($this->RealStrings as $str)
			$this->Length += $str->Length();
	}
	
	function Length() {
		$this->_CalculateLength();
		return $this->Length;
	}
	
	function &Characters($from, $len) {
		$x = &new CStringChainIterator($this, $from, $len);
		return $x;
	}
	
	// TODO function Substring()
}

class CStringChainIterator extends CCharIterator {
	var $RealStrings;
	var $Remaining;
	var $Ite;
	
	function Init($str, $from, $len) {
		$this->RealStrings = $str->RealStrings;
		
		while (sizeof($this->RealStrings) > 0 && $from >= $this->RealStrings[0]->Length()) {
			$from -= $this->RealStrings[0]->Length();
			array_splice($this->RealStrings, 0, 1);
		}
		
		if (sizeof($this->RealStrings) > 0)
			$this->Ite = &$this->RealStrings[0]->Characters($from, $len);
		$this->Remaining = $len;
	}
	
	function NextChar() {
		if (is_null($this->Ite))
			return null;
		if ($this->Remaining <= 0)
			return null;
		
		$c = $this->Ite->NextChar();
		while (is_null($c)) {
			$this->Ite = null;
			array_splice($this->RealStrings, 0, 1);
			if (sizeof($this->RealStrings) == 0)
				return null;
			
			$this->Ite = &$this->RealStrings[0]->Characters(0, $this->Remaining);
			$c = $this->Ite->NextChar();
		}
		
		$this->Remaining--;
		return $c;
	}
}

?>